﻿using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Configuration;
using SlamCms.Common;

namespace SlamCms.Web.Mvc
{
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
	public class HandleExceptionAttribute : FilterAttribute, IExceptionFilter
	{
		public string ExceptionRedirectUrl { get; set; }
		public string ApplicationExceptionRedirectUrl { get; set; }
		
		public void OnException(ExceptionContext filterContext)
		{
			if (filterContext == null)
				throw new ArgumentNullException("filterContext");

			if (!filterContext.IsChildAction && !filterContext.ExceptionHandled && filterContext.HttpContext.IsCustomErrorEnabled)
			{
				if (filterContext.Exception is ApplicationException)
					this.HandleApplicationException(filterContext);
				else
					this.HandleException(filterContext);
			}
		}

		protected void HandleApplicationException(ExceptionContext filterContext)
		{
			var exception = filterContext.Exception as ApplicationException;

			if (filterContext.HttpContext.Request.IsAjaxRequest())
			{
				var jsonResult = new NewtonJsonResult(new { Error = exception.Message }, JsonRequestBehavior.AllowGet);
				filterContext.Result = jsonResult;
			}
			else
			{
				if (!this.ApplicationExceptionRedirectUrl.IsNullOrWhiteSpace())
				{
					filterContext.Result = new RedirectResult(this.ApplicationExceptionRedirectUrl);
				}
				else
				{
					var result = new ViewResult() { ViewName = "Message" };
					var model = new MessageViewModel()
					{
						Title = "Sorry, an error has ocurred".ToHtml(),
						Description = exception.Message.ToHtml()
					};
					result.ViewData = new ViewDataDictionary<MessageViewModel>(model);
					filterContext.Result = result;
				}
			}

			filterContext.ExceptionHandled = true;
			filterContext.HttpContext.Response.Clear();
			filterContext.HttpContext.Response.StatusCode = 200;
			filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
		}

		protected void HandleException(ExceptionContext filterContext)
		{
			var exception = filterContext.Exception;

			if (new HttpException(null, exception).GetHttpCode() == 500)
			{
				if (filterContext.HttpContext.Request.IsAjaxRequest())
				{
					var jsonResult = new JsonResult();
					var msg = "An error has ocurred";
					jsonResult.Data = new { Error = msg };
					filterContext.Result = jsonResult;
				}
				else
				{
					if (!this.ExceptionRedirectUrl.IsNullOrWhiteSpace())
					{
						filterContext.Result = new RedirectResult(this.ExceptionRedirectUrl);
					}
					else
					{
						var result = new ViewResult() { ViewName = "Error" };
						var model = new ErrorViewModel()
						{
							Title = "Sorry, an error has ocurred",
							Description = "Please try again later",
							ShowTechnicalDetails = bool.Parse(WebConfigurationManager.AppSettings["ShowErrorDetails"]),
							TechnicalDetails = exception.ToString()
						};
						result.ViewData = new ViewDataDictionary<ErrorViewModel>(model);
						filterContext.Result = result;
					}
				}

				filterContext.HttpContext.Response.StatusCode = 500;
				filterContext.ExceptionHandled = true;
				filterContext.HttpContext.Response.Clear();
				filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
			}
		}
	}
}
